// STM32服务器代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "cJSON.h"
#include "shmem.h"
#include "msg_queue_peer.h"

#define SERVER_PORT 8080      // 服务器端口号
#define DATA_BUFFER_SIZE 1024 // 数据缓冲区大小
struct sockaddr_in server_addr, client_addr;
char dataBuffer[3096] = "";
int clientfd;

typedef struct
{
    int key;
    char name[32];
    int type;
    int typeStata;
    int value;
    float floatValue;
} Stm32Data;

typedef struct
{
    int key;
    char name[32];
    int addr;
    int type;
    int typeStata;
    int value;
} ModbusData;

typedef struct
{
    int key;
    char name[32];
    int type;
    int typeStata;
    int addr;
    int value;
} MetaServerData;

typedef struct
{
    Stm32Data stm32_list[8];   // 固定数组，存储stm32数据
    int stm32_count;           // 实际有效数量
    ModbusData modbus_list[6]; // 固定数组，存储modbus数据
    int modbus_count;
    MetaServerData meta_list[7]; // 固定数组，存储metaServer数据
    int meta_count;
} DeviceData;

// 消息队列结构体
struct msgbuf
{
    long mtype;
    char mdata[256];
};

void *msg_queue_send_thread(void *arg)
{
    struct msgbuf recv_buf;

    while (1)
    {
        if (msg_queue_recv("stm32", &recv_buf, sizeof(recv_buf), 0, 0) > 0)
        {
            cJSON *root = cJSON_Parse(recv_buf.mdata);
            cJSON *stm32 = cJSON_GetObjectItem(root, "stm32");
            char *stm32_str = cJSON_PrintUnformatted(stm32);
            sendto(clientfd, stm32_str, strlen(stm32_str), 0, (struct sockaddr *)&client_addr, sizeof(client_addr));
            printf("%s\n", stm32_str);

            cJSON_Delete(root);
            free(stm32_str);
        }
    }
    return NULL;
}
void *shmem_write_thread(void *arg)
{

    printf("shmem_write_thread\n");
    static struct shm_param para;

    int ret = shm_init(&para, "main.c", sizeof(DeviceData));
    if (ret < 0)
    {
        pthread_exit(NULL);
    }

    //  获取共享内存地址
    DeviceData *shm_device = (DeviceData *)shm_getaddr(&para);
    if (!shm_device)
    {
        perror("shm_getaddr failed");
        pthread_exit(NULL);
    }

    // 接收消息
    while (1)
    {
        int readDataNumber = recv(clientfd, dataBuffer, sizeof(dataBuffer), 0);
        if (readDataNumber < 0)
        {
            perror("接收数据失败");
            close(clientfd);
            break;
        }
        else if (readDataNumber == 0)
        {
            printf("客户端 %s:%d 已断开连接\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
            break;
        }
        else
        {
            // 查找@符号位置进行数据拆解
            char *data_ptr = strstr(dataBuffer, "@");
            // 如果找到@，从@后面开始解析；否则使用原始数据
            char *parse_data = (data_ptr != NULL) ? (data_ptr + 1) : dataBuffer;

            // printf("原始接收数据: %s\n", dataBuffer);
            // printf("拆解后解析数据: %s\n", parse_data);

            //  json的反序列化（使用拆解后的数据）
            cJSON *root = cJSON_Parse(parse_data);

            if (NULL == root)
            {
                printf("parse err\n");
                pthread_exit(NULL);
            }

            cJSON_Print(root);

            // 获取根节点上名字叫stm32的子节点
            cJSON *stm32 = cJSON_GetObjectItem(root, "stm32");
            cJSON *dataArry = cJSON_GetObjectItem(stm32, "data");
            cJSON *tmp = NULL; // stm32数组节点

            for (int i = 0; i < shm_device->stm32_count; i++)
            {
                tmp = cJSON_GetArrayItem(dataArry, i);
                cJSON *key = cJSON_GetObjectItem(tmp, "key");
                shm_device->stm32_list[i].key = atoi(key->valuestring);
                shm_device->stm32_list[i].type = 2;
                shm_device->stm32_list[i].typeStata = 2;
                if (atoi(key->valuestring) == 1001)
                {
                    strcpy(shm_device->stm32_list[i].name, "冷藏柜");
                    cJSON *value = cJSON_GetObjectItem(tmp, "value");
                    shm_device->stm32_list[i].value = value->valueint;
                    shm_device->stm32_list[i].floatValue = 0;
                }
                else if (atoi(key->valuestring) == 1002)
                {
                    strcpy(shm_device->stm32_list[i].name, "电源插座");
                    cJSON *value = cJSON_GetObjectItem(tmp, "value");
                    shm_device->stm32_list[i].value = value->valueint;
                    shm_device->stm32_list[i].floatValue = 0;
                }
                else if (atoi(key->valuestring) == 1003)
                {
                    strcpy(shm_device->stm32_list[i].name, "门锁");
                    cJSON *value = cJSON_GetObjectItem(tmp, "value");
                    shm_device->stm32_list[i].value = value->valueint;
                    shm_device->stm32_list[i].floatValue = 0;
                }
                else if (atoi(key->valuestring) == 1004)
                {
                    strcpy(shm_device->stm32_list[i].name, "排风扇");
                    cJSON *value = cJSON_GetObjectItem(tmp, "value");
                    shm_device->stm32_list[i].value = value->valueint;
                    shm_device->stm32_list[i].floatValue = 0;
                }
                else if (atoi(key->valuestring) == 1005)
                {
                    strcpy(shm_device->stm32_list[i].name, "灯光状态");
                    cJSON *value = cJSON_GetObjectItem(tmp, "value");
                    shm_device->stm32_list[i].value = value->valueint;
                    shm_device->stm32_list[i].floatValue = 0;
                }
                else if (atoi(key->valuestring) == 1006)
                {
                    strcpy(shm_device->stm32_list[i].name, "温度传感器");
                    cJSON *floatValue = cJSON_GetObjectItem(tmp, "floatValue");
                    shm_device->stm32_list[i].value = 0;
                    shm_device->stm32_list[i].floatValue = floatValue->valuedouble;
                }
                else if (atoi(key->valuestring) == 1007)
                {
                    strcpy(shm_device->stm32_list[i].name, "湿度传感器");
                    cJSON *floatValue = cJSON_GetObjectItem(tmp, "floatValue");
                    shm_device->stm32_list[i].value = 0;
                    shm_device->stm32_list[i].floatValue = floatValue->valuedouble;
                }
                else if (atoi(key->valuestring) == 1008)
                {
                    strcpy(shm_device->stm32_list[i].name, "险情警报");
                    cJSON *value = cJSON_GetObjectItem(tmp, "value");
                    shm_device->stm32_list[i].value = value->valueint;
                    shm_device->stm32_list[i].floatValue = 0;
                }
            }
            for (int i = 0; i < shm_device->stm32_count; i++)
            {
                printf("key=%d\n", shm_device->stm32_list[i].key);
                printf("name=%s\n", shm_device->stm32_list[i].name);
                printf("type=%d\n", shm_device->stm32_list[i].type);
                printf("typeStata=%d\n", shm_device->stm32_list[i].typeStata);
                printf("value=%d\n", shm_device->stm32_list[i].value);
                printf("floatValue=%f\n", shm_device->stm32_list[i].floatValue);
                printf("\n");
            }
            // 释放json
            cJSON_Delete(root);
            // 清空缓冲区
            memset(dataBuffer, 0, sizeof(dataBuffer));
        }
    }
    return NULL;
}

int main(int argc, char const *argv[])
{
    // 创建流式套接字(TCP)
    int severSockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (severSockfd < 0)
    {
        perror("创建套接字失败");
        return -1;
    }
    printf("创建套接字成功，套接字描述符: %d\n", severSockfd);

    // 设置端口复用
    int opt = 1;
    if (setsockopt(severSockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))
    {
        perror("设置套接字选项失败");
        close(severSockfd);
        exit(EXIT_FAILURE); // 端口复用失败
    }
    // 指定网络信息
    /*
    sin_family:IPv4协议族
    sin_port:端口号（转换为网络字节序）两个字节
    sin_addr.s_addr:主机字节序转换为网络字节序，虚拟机IP
    */
    server_addr.sin_family = AF_INET;          // AF_INET:IPV4
    server_addr.sin_port = htons(SERVER_PORT); // 端口号
    server_addr.sin_addr.s_addr = INADDR_ANY;  // IP地址

    // 绑定套接字
    if (bind(severSockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        perror("绑定端口失败");
        close(severSockfd);
        exit(EXIT_FAILURE);
    }
    printf("绑定端口 %d 成功\n", SERVER_PORT);

    // 监听，将主动套接字变为被动套接字
    if (listen(severSockfd, 8) < 0)
    {
        perror("监听失败");
        close(severSockfd);
        exit(EXIT_FAILURE);
    }
    printf("TCP服务器已启动，监听端口 %d...\n", SERVER_PORT);
    printf("等待客户端连接...\n");

    // 接收客户端连接请求
    int len = sizeof(client_addr);
    clientfd = accept(severSockfd, (struct sockaddr *)&client_addr, &len);
    if (clientfd < 0)
    {
        perror("accept err");
        close(severSockfd);
        exit(EXIT_FAILURE);
    }
    // 打印连接的客户端信息
    printf("客户端已连接: %s:%d (套接字: %d)\n",
           inet_ntoa(client_addr.sin_addr),
           ntohs(client_addr.sin_port),
           clientfd);
    pthread_t msgQueueTid; // 创建消息队列线程
    pthread_t shmemTid;    // 创建共享内存线程
    if (pthread_create(&msgQueueTid, NULL, msg_queue_send_thread, NULL) != 0)
    {
        perror("create thread err");
        return -1;
    }
    if (pthread_create(&shmemTid, NULL, shmem_write_thread, NULL) != 0)
    {
        perror("create thread err");
        return -1;
    }
    // 等待线程结束
    pthread_join(msgQueueTid, NULL);
    pthread_join(shmemTid, NULL);
    // pthread_detach(msgQueueTid);
    // pthread_detach(shmemTid);

    close(clientfd);
    close(severSockfd);
    printf("服务器已关闭\n");
    return 0;
}
